#ifndef __CLIENT_H__
#define __CLIENT_H__

#include <cstdint>
#include <memory>
#include <vector>
#include <mutex>
#include "Engine/GameGuid.h"
#include "LiteNetLib/NetPeer.h"
#include "GameEnum.h"


using namespace LiteNetLib;
using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    class PlayerData;
    class IPackage;

    class Client : public std::enable_shared_from_this<Client>
    {
    private:
        float m_loadtime;
        std::string m_ip;

        std::vector<std::shared_ptr<IPackage>> m_waitHandlePackageVec;
        std::vector<std::shared_ptr<IPackage>> m_waitHandlePackageVecCatch;
        std::mutex m_waitHandlePackageMutex;


        // 计时，用于减少异常次数， 1秒减少异常次数1
        float m_abnormalDecTime = 0.0f;

        // 异常次数，超过特定的值时会被断开连接,(50次时会强制断开连接)
        std::atomic<uint16_t> m_abnormalCount = 0;

    public:
        std::string communityId = "";
        ClientState state;
        std::string nickname = "";
        GameGuid guid;

        // x24.03.04 的元素
        GameGuid tokenId;
        // ======================

        // 混淆的guid，防止盗号狗
        GameGuid confusionGuid;

        std::shared_ptr<PlayerData> playerData = nullptr;

        uint8_t clientID;
        NetPeerPtr netPeer;

        bool isEntityLoad();

        Client(NetPeerPtr theNetPeerPtr, const GameGuid &theGuid, uint8_t theClientID, const std::string &theNickname);
        virtual ~Client();

        void update(float dt);

        void createPlayerDataUseMsgJson(const nlohmann::json &jsonData);
        void loadPlayerData(const nlohmann::json &jsonData);

        void disconnect(const std::string& message = "");
        void handleDisconnected();

        void addWaitHandlePackage(std::shared_ptr<IPackage> &package);

        inline void addAbnormalCount(uint16_t count);

        inline size_t getHashCode();
        inline const std::string &getIP();
        inline const std::string &getAddress();

        inline void send(const char *buff, uint32_t buffSize, DeliveryMethod deliveryMethod);
        inline void send(const char *buff, uint32_t buffSize, uint8_t channelNumber, DeliveryMethod deliveryMethod);

    };

    inline void Client::addAbnormalCount(uint16_t count)
    {
        m_abnormalCount += count;
    }
    inline size_t Client::getHashCode()
    {
        return netPeer->getHashCode();
    }
    inline const std::string &Client::getIP()
    {
        return m_ip;
    }
    inline const std::string &Client::getAddress()
    {
        return netPeer->getAddress();
    }

    inline void Client::send(const char *buff, uint32_t buffSize, DeliveryMethod deliveryMethod)
    {
        netPeer->send(buff, buffSize, 0, deliveryMethod);
    }
    inline void Client::send(const char *buff, uint32_t buffSize, uint8_t channelNumber, DeliveryMethod deliveryMethod)
    {
        netPeer->send(buff, buffSize, channelNumber, deliveryMethod);
    }

    typedef std::shared_ptr<Client> ClientPtr;

}

#endif